package by.twouexplorer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Currency;
import java.util.List;
import java.util.zip.Inflater;

import android.R.string;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.MimeTypeMap;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.SweepGradient;
import android.app.AlertDialog.Builder;

public class TwoUExplorerMain extends ListActivity implements OnTaskCompleteListener{
	
	
	private List<MetaData> directoryData = new ArrayList<MetaData>();
	List<MetaData> tempFileList = new ArrayList<MetaData>(); 
	private File currentDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath());	
	private Adapter adapter;  //Adapter
	private ListView lv; //List View
	private AsyncTaskManager mAsyncTaskManager;
	AdapterView.AdapterContextMenuInfo info;
	private final int RENAME_DIALOG = 1;
	private final int TWO_BUTTONS = 0;
	private final int OVERWRITE=2;
	private final int NEW_FOLDER=3;
	private final int FILE_OR_FOLDER = 4;
    private final int NEW_FILE = 5;
    private final int PROPERTIES = 6;
    private final int PASTE_MENU_ID=7;
   	private boolean isCopyPaste;
	private boolean isCutPaste;
	private File fileToCopy;
	private File fileToCut;
	private MetaData propertiesFile;
	private boolean isContinue;
	private String name;
	private File sourceFile;
	private String newFile;
	private EditText editName;
	private TextView nameView;
	private TextView pathView;
	private TextView sizeView;
	private TextView lastModifiedView;
	private String path;
	private FileWorker worker;
	public static String upperLevel="..";
	public static String txtToOpen;
			 
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		String action=this.getIntent().getAction();
		this.adapter=new Adapter(this);
	    // Create manager and set this activity as context and listener
		mAsyncTaskManager = new AsyncTaskManager(this, this);
		// Handle task that can be retained before
		mAsyncTaskManager.handleRetainedTask(getLastNonConfigurationInstance());
	    sourceFile = new File(""); 
	    worker = new FileWorker();
	    newFile = new String();
	    lv = getListView(); 
	    registerForContextMenu(lv);
	    lv.setAdapter(adapter);
	    isCopyPaste=false;
	    isCutPaste = false;
	    lv.setOnItemClickListener(new AdapterView.OnItemClickListener()	{
	    	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
	    		File file = new File(((MetaData)adapter.getItem(position)).getPath());
	        	String selectedFileString = ((MetaData)adapter.getItem(position)).getName();
	        	if(selectedFileString.equals(upperLevel)){
	        		upOneLevel(); //if ".." element is chosen go to the upper level
	        	}
	        	else
	        	   	select(file); //else handle the click on file or directory
	        	}
	        });
	    if (action.equals(StartScreen.rootSDBrowseAction))
	    	select(new File(Environment.getExternalStorageDirectory().getAbsolutePath()));
	    else if (action.equals(StartScreen.downloadBrowseAction) && (new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download").exists()))
	    	select(new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download"));
	    else if (action.equals(StartScreen.galleryBrowseAction) && new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/DCIM").exists())
	    	select(new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/DCIM"));
	    else if (action.equals(StartScreen.musicBrowseAction) && new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Music").exists())
	    	select(new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Music"));
	    else {
	    	Toast.makeText(this, "Couldn't find directory", Toast.LENGTH_LONG).show();
	    	select(new File(Environment.getExternalStorageDirectory().getAbsolutePath()));
	    }
	}
	 
	void select(final File file){ //Handling the click on the file or directory
		 if(Adapter.isProtected(file)) //If directory is protected
	        {
	                new Builder(this) //Show alert dialog
	                        .setIcon(android.R.drawable.ic_dialog_alert)
	                        .setTitle("Access denied")
	                        .setMessage("Can't open directory " + file.getName())
	                        .show();
	        }
		 else if (file.isDirectory()){ //If directory is clicked
			 currentDirectory = file; 
		     fill(file.listFiles()); //Renew elements list
		     TextView titleManager = (TextView) findViewById(R.id.titleManager);
		     titleManager.setText(file.getAbsolutePath());
		 }
		 else { //If file is clicked
			 if(Adapter.isProtected(file) || file.isDirectory())
             {
                     return;
             }
             Intent intent = new Intent();
             intent.setAction(android.content.Intent.ACTION_VIEW);
             Uri uri = Uri.fromFile(file);
             String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(uri.toString()));
             intent.setDataAndType(uri,type==null?"*/*":type);
             startActivity((Intent.createChooser(intent, "Open using"))); //Opening file			
		 }		 
	}
	 
	private void fill(final File[] files) { //Filling list view with files and directories
		 new Thread(new Runnable() { //Creating separate thread
		        public void run() {
		        	directoryData.clear();
		        	tempFileList.clear();
		        	if (currentDirectory.getParent() != null && !currentDirectory.equals(Environment.getExternalStorageDirectory()))
		        		directoryData.add(new MetaData(upperLevel)); //adding upper level button
		        	for (File file : files) {
		        		if(file.isDirectory())
		        			directoryData.add(new MetaData(file.getAbsolutePath(), file.length(), file.lastModified()));
		        		else tempFileList.add(new MetaData(file.getAbsolutePath(), file.length(), file.lastModified()));
		        	}
		        	if(!tempFileList.isEmpty()){
		        		for (MetaData file : tempFileList)
		        			directoryData.add(file);
		        	}
		        	
		        	adapter.setItems(directoryData);
		        }
		 }).run();
	}
	 
	 @Override
	public void onBackPressed() //Back button press handle
	{
		 if(currentDirectory.equals(Environment.getExternalStorageDirectory()))
			 super.finish(); //Exit if current position is root of SD-Card
		 else upOneLevel(); //Else go to parent directory
	}
		  
	 @Override
	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { //Creating context menu
		 super.onCreateContextMenu(menu, v, menuInfo);
		 name = new String();
		 MenuInflater inflater = getMenuInflater();
		 inflater.inflate(R.layout.context_menu, menu);
		 menu.setHeaderTitle(R.string.actions);
		 AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
		 MetaData myItem = (MetaData) adapter.getItem(info.position);
		 txtToOpen = myItem.getPath().toString();
		 if(!myItem.getName().toString().endsWith(".txt")) menu.removeItem(R.id.textEditId);
		 if(!isCopyPaste && !isCutPaste) menu.removeItem(R.id.pasteId);
	}
		 
	@Override
	public boolean onContextItemSelected(MenuItem item)
	{
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
		MetaData myItem = (MetaData) adapter.getItem(info.position);
		//if(!myItem.getName().toString().endsWith(".txt"))  
	 	if (item.getItemId() == R.id.copyId) { //If copy button is clicked
	 		isCopyPaste=true;	//Enabling CopyPaste mode 		
	 		fileToCopy=new File(myItem.getPath()); //Creating the source file and waiting till Paste button will be pressed
				 			
		} else if (item.getItemId() == R.id.cutId) {
			                                                                        //CUT
			isCutPaste = true;                                                                      //CUT		
			fileToCut = new File(myItem.getPath());
			
		} else if (item.getItemId() == R.id.pasteId) { //If Paste button is pressed
			if(isCopyPaste) //If CopyPaste mode is enabled
			{
				File dest; //Destination file
				isContinue=true; //Permission to continue if name of destination file already exists
				if(myItem.getPath().equals("/"+upperLevel)) dest=new File(currentDirectory+"/" +fileToCopy.getName());
				else if(myItem.getFile().isDirectory()) //Will paste it inside the clicked directory
					dest = new File(myItem.getPath() + "/" + fileToCopy.getName());
				else dest = new File(currentDirectory+"/" +fileToCopy.getName()); //will paste it inside current directory
				if(dest.exists()) //if destination file already exists
					showDialog(OVERWRITE); //Dialog offer to choose if user wants to overwrite the file
				if(isContinue) //If permission to overwrite is accepted
				{
					//Coping routine
					mAsyncTaskManager.setupTask(new Copier(getResources(), fileToCopy.getAbsolutePath(), dest.getAbsolutePath()));
					isCopyPaste=false; //Disabling CopyPaste mode
					refreshList();
				}
			} else if(isCutPaste) {                                                
				//CUT --> PASTE
				if(myItem.getPath().equals("/"+upperLevel)) newFile = myItem.getPath() + "/" + fileToCut.getName();
				else if(myItem.getFile().isDirectory()) //Will paste it inside the clicked directory
					newFile = myItem.getPath() + "/" + fileToCut.getName();
				else newFile = currentDirectory + "/" +fileToCut.getName();
				worker.move(fileToCut, new File(newFile));
				refreshList();
				isCutPaste=false;
			} 
		} else if (item.getItemId() == R.id.renameId) {  
			name = myItem.getPath();
			sourceFile = new File(name);
			showDialog(RENAME_DIALOG);
			
		} else if (item.getItemId() == R.id.newFileId) {
			//new file
			if(myItem.getPath().equals("/"+upperLevel)) newFile=currentDirectory.getAbsolutePath();
			else if(myItem.getFile().isDirectory()) //Will paste it inside the clicked directory
				newFile=myItem.getPath();
			else newFile=currentDirectory.getAbsolutePath();
			showDialog(FILE_OR_FOLDER);
		} else if (item.getItemId() == R.id.deleteId) {
			//delete
			if(myItem.getPath().equals("/"+upperLevel)) return true;
			path=myItem.getPath();
			showDialog(TWO_BUTTONS);
		} else if(item.getItemId()== R.id.propertiesId){
			if(myItem.getPath().equals("/"+upperLevel)) return true;
			propertiesFile=new MetaData(myItem.getFile(), myItem.getName(), myItem.getSize(), myItem.getLastModified());
			showDialog(PROPERTIES);			
			
		}
		else if(item.getItemId()==R.id.textEditId){
			Intent textReaderIntent= new Intent();
			textReaderIntent.setAction("twouexplorer.by.textAcion");
			textReaderIntent.setClass(getApplicationContext(), TextEditor.class);
			textReaderIntent.putExtra(Intent.EXTRA_TEXT, txtToOpen);
			startActivity(textReaderIntent);
		}
		else {
			return super.onContextItemSelected(item);
		}
	 	
	 	return true;
	}
		 
	@Override
	protected Dialog onCreateDialog(int id)
		{
	    	switch (id) 
			{
	    	case OVERWRITE: //Dialog to solve if file should be overwritten
	    		AlertDialog.Builder bldr = new AlertDialog.Builder(this);
				bldr.setMessage("File already exists. Do you want to overwrite it?")
				        .setCancelable(false)
				        .setPositiveButton("Yes", new DialogInterface.OnClickListener() 
					    {
				            public void onClick(DialogInterface dialog, int id) { //If Yes button clicked 
				                isContinue=true; //Set permission to overwrite
				            }
				        })
						.setNegativeButton("No", new DialogInterface.OnClickListener() 
						{
				           public void onClick(DialogInterface dialog, int id)  //If No button is clicked
						    {
				        	   isContinue=false; //Deny permission
				        	   dialog.cancel();
				            }  
				        });
				AlertDialog alrt = bldr.create();
	            return bldr.create();
			case TWO_BUTTONS:
				AlertDialog.Builder builder = new AlertDialog.Builder(this);
				builder.setMessage("Are you sure?")
				        .setCancelable(false)
				        .setPositiveButton("Yes", new DialogInterface.OnClickListener() 
					    {
				            public void onClick(DialogInterface dialog, int id) {
				            	if(worker.deleteTarget(path)) refreshList();
				            	else Toast.makeText(getApplicationContext(), "Can't delete file" +name, Toast.LENGTH_SHORT).show();
				            }
				        })
						.setNegativeButton("Cancel", new DialogInterface.OnClickListener() 
						{
				           public void onClick(DialogInterface dialog, int id) 
						    {
				                dialog.cancel();
				            }  
				        });
				AlertDialog alert = builder.create();
	            return builder.create();
			
			case RENAME_DIALOG:
				LayoutInflater inflater = getLayoutInflater(); 
				View layout = inflater.inflate(R.layout.rename_dialog, 
				    (ViewGroup)findViewById(R.id.toast_layout)); 
				editName = (EditText)layout.findViewById(R.id.editName);
				builder = new AlertDialog.Builder(this); 
				builder.setView(layout); 
				builder.setMessage("Rename of File"); 
				builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { 	
				    public void onClick(DialogInterface dialog, int id) 
				    {
				    	 newFile = sourceFile.getParent() + "/" + editName.getText();
				    	 worker.rename(sourceFile,new File(newFile));
				    	 refreshList();
				    }
				});
				builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
				{
				    public void onClick(DialogInterface dialog, int id) 
					{
						dialog.cancel(); 
					} 
				});
				builder.setCancelable (false); 
				
				return builder.create();
				
			case FILE_OR_FOLDER:
				AlertDialog.Builder builder1 = new AlertDialog.Builder(this);
				builder1.setMessage("Create new:")
				        .setCancelable(false)
				        .setPositiveButton("File", new DialogInterface.OnClickListener() 
					    {
				            public void onClick(DialogInterface dialog, int id) {
				            	
				            	showDialog(NEW_FILE);

				            }

				        })
						.setNegativeButton("Folder", new DialogInterface.OnClickListener() 
						{
				           public void onClick(DialogInterface dialog, int id) 
						    {
				        	   showDialog(NEW_FOLDER);
				            }  
				        });
				AlertDialog alert1 = builder1.create();
	            return builder1.create();
				
			case NEW_FOLDER:
				LayoutInflater inflater1 = getLayoutInflater(); 
				View layout1 = inflater1.inflate(R.layout.new_folder,(ViewGroup)findViewById(R.id.newFolder_layout)); 
				editName = (EditText)layout1.findViewById(R.id.newFolder);
				builder1 = new AlertDialog.Builder(this); 
				builder1.setView(layout1); 
				builder1.setMessage("Name of Folder"); 
				builder1.setPositiveButton( 
				    "Ok", new DialogInterface.OnClickListener() 
				{ 
				    public void onClick(DialogInterface dialog, int id) 
				    {
				    	String name = editName.getText().toString();
			            if (worker.createDir(newFile, name)) refreshList();
			            else  Toast.makeText(getApplicationContext(), "Can't create folder" +name, Toast.LENGTH_SHORT).show();
			        }
				});
				builder1.setNegativeButton( 
					"Cancel", new DialogInterface.OnClickListener() 
				{
				    public void onClick(DialogInterface dialog, int id) 
					{
					    dialog.cancel(); 
					} 
				});
				builder1.setCancelable (false); 
				return builder1.create();
				
			case NEW_FILE:
				LayoutInflater inflater2 = getLayoutInflater(); 
				View layout2 = inflater2.inflate(R.layout.new_file,(ViewGroup)findViewById(R.id.newFile_layout)); 
				editName = (EditText)layout2.findViewById(R.id.newFile);
				builder1 = new AlertDialog.Builder(this); 
				builder1.setView(layout2); 
				
				builder1.setMessage("Name of File"); 
				builder1.setPositiveButton( 
				    "Ok", new DialogInterface.OnClickListener() 
				{ 
				    public void onClick(DialogInterface dialog, int id) 
				    {
				    	String name = editName.getText().toString();
			            worker.createFile(newFile, name);
			            refreshList();
			        }
				});
				builder1.setNegativeButton( 
					"Cancel", new DialogInterface.OnClickListener() 
				{
				    public void onClick(DialogInterface dialog, int id) 
					{
					    dialog.cancel(); 
					} 
				});
				builder1.setCancelable (false); 
				return builder1.create();
			case PROPERTIES:
				LayoutInflater propertiesInflater = getLayoutInflater(); 
				View propertyLayout = propertiesInflater.inflate(R.layout.custom_dialog,(ViewGroup)findViewById(R.id.layout_dialog)); 
				builder1 = new AlertDialog.Builder(this); 
				builder1.setView(propertyLayout); 
				builder1.setMessage(getString(R.string.properties_text));
				nameView = (TextView)propertyLayout.findViewById(R.id.file_name);
				pathView = (TextView)propertyLayout.findViewById(R.id.file_path);
				sizeView = (TextView)propertyLayout.findViewById(R.id.file_size);
				lastModifiedView = (TextView)propertyLayout.findViewById(R.id.last_modified);
				builder1.setPositiveButton( 
				    "Ok", new DialogInterface.OnClickListener() 
				{ 
				    public void onClick(DialogInterface dialog, int id) 
				    {
				    	dialog.cancel();
			        }
				});
				 
				return builder1.create();
				
			default:
				return null;
					
			}
	    }
	 
	private void upOneLevel(){ //Go to parent directory
		 if(this.currentDirectory.getParent() != null && !currentDirectory.getAbsolutePath().equals(Environment.getExternalStorageDirectory())) {
			 select(currentDirectory.getParentFile());
		 }
		 else Toast.makeText(getApplicationContext(), "Attempting to get out from sdcard directory", Toast.LENGTH_SHORT).show();
	 }
	  
	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		if(id == RENAME_DIALOG) {
		editName.setText(sourceFile.getName());
		} 
		else if (id==NEW_FOLDER){
			editName.setText("");
		}
		else if (id==NEW_FILE){
			editName.setText("");
		}
		else if (id==PROPERTIES){
			sizeView.setVisibility(0);
			nameView.setText(getString(R.string.name)+" "+propertiesFile.getName());
			pathView.setText(getString(R.string.path)+" "+propertiesFile.getPath());
			if(propertiesFile.getFile().isDirectory()) sizeView.setVisibility(4); //invisible
			else sizeView.setText(getString(R.string.size)+" "+Long.toString(propertiesFile.getSize())+" bytes");
			lastModifiedView.setText(getString(R.string.modified)+" "+propertiesFile.getLastModified().toGMTString());
		}
		super.onPrepareDialog(id, dialog);
		
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.layout.options_menu, menu);
	    
	    return true;
	}
	
	@Override
	public boolean onPrepareOptionsMenu(Menu menu){
		if(isCopyPaste || isCutPaste){
			if(menu.findItem(PASTE_MENU_ID)==null)
				menu.add(0, PASTE_MENU_ID, 0, "Paste");
		}
		else{
			if(menu.findItem(PASTE_MENU_ID) != null)
				menu.removeItem(PASTE_MENU_ID);
		}
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
	    // Handle item selection
	    switch (item.getItemId()) {
	    case R.id.new_folder_menu:
	        newFile=new String(currentDirectory.getAbsolutePath());
	        showDialog(FILE_OR_FOLDER);
	        return true;
	    case R.id.refresh_menu:
	        refreshList();
	        return true;
	    case PASTE_MENU_ID:
	    	if(isCopyPaste){
	    		File dest = new File(currentDirectory+"/" +fileToCopy.getName());
	    		isContinue=true;
	    		if(dest.exists()) //if destination file already exists
	    			showDialog(OVERWRITE); //Dialog offer to choose if user wants to overwrite the file
	    		if(isContinue) //If permission to overwrite is accepted
	    		{
	    			//Coping routine
	    			mAsyncTaskManager.setupTask(new Copier(getResources(), fileToCopy.getAbsolutePath(), dest.getAbsolutePath()));
	    			isCopyPaste=false; //Disabling CopyPaste mode
	    			refreshList();
	    		}
	    	}
	    	if(isCutPaste){
	    		newFile = currentDirectory + "/" +fileToCut.getName();
				worker.move(fileToCut, new File(newFile));
				refreshList();
				isCutPaste=false;	    		
	    	}
	    default:
	        return super.onOptionsItemSelected(item);
	    }
	}
	 
	public void refreshList(){ //reloading files/directories list
		select(currentDirectory);
	}
	
	@Override
	public Object onRetainNonConfigurationInstance() {
		// Delegate task retain to manager
		return mAsyncTaskManager.retainTask();
	}

	
	public void onTaskComplete(Copier task) {
		if (task.isCancelled()) {
		    // Report about cancel
		    Toast.makeText(this, "Task Canceled", Toast.LENGTH_LONG).show();
		} else {
		    // Get result
		    Boolean result = null;
		    try {
			result = task.get();
		    } catch (Exception e) {
			e.printStackTrace();
		    }
		    // Report about result
		    Toast.makeText(this, ("Completed " + ((result != null) ? "successfully" : "with error")), Toast.LENGTH_LONG).show();
		    refreshList();
		}
	}
	
}
